﻿using Avalonia.Controls;
using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Runtime;
using SkiaSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace LightCAD.Drawing
{
    public class DimRadialAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;

        static DimRadialAction()
        {
            CommandName = "DIMRADIAL";
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "DDI",
                Description = "DIMRADIAL",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep{ Name="Step0", Options="选择圆或圆弧:" },
                }
            };
            
        }

        internal static void Initilize()
        {
            ElementActions.DimRadial = new DimRadialAction();
            LcDocument.ElementActions.Add(BuiltinElementType.DimRadial, ElementActions.DimRadial);
        }

        private PointInputer inputer { get; set; }

        private Vector2d? point;
        private Vector2d? center;
        private double raduis;
        public DimRadialAction() { }
        public DimRadialAction(DocumentRuntime docRt) : base(docRt)
        {
            docRt.CommandCtrl.WriteInfo("命令 ：DIMRADIAL");
        }
        private LcCreateMethod GetMethod(string method)
        {
            if (method == null) return CreateMethods[0];
            var getted= CreateMethods.FirstOrDefault((m) => m.Name == method);
            if (getted == null)
                return CreateMethods[0];
            else
                return getted;
        }
        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            //this.Segments = new List<RolineSegment>();
            var curMethod = CreateMethods[0];
            var ElementInputer = new ElementInputer(this.docRt);
            this.inputer = new PointInputer(this.docRt);
            Step0:
            var step0 = curMethod.Steps[0];


            var result0 = await ElementInputer.Execute(step0.Options);
            if (ElementInputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result0.Value == null)
            {
                goto Step0;
            }
            else
            {
                LcElement element = (LcElement)result0.Value;
                this.point = (Vector2d)result0.Extent;
                if (CreateSelects(element))
                {
                    //记住圆的圆心点 以及半径
                    if (this.docRt.Action.SelectedElements[0] is LcCircle)
                    {
                        var circle = element as LcCircle;
                        this.center = circle.Center;
                        this.raduis = circle.Radius;
                        #region
                        LcLine lcline = new LcLine(circle.Center, this.point.Value);
                        //需要移动的向量方向
                        Vector2d direction = new Vector2d(0, 0);
                        //需要移动的距离
                        double dis = Math.Abs(lcline.Length - this.raduis);
                        if (lcline.Length > this.raduis) {
                            //向内延伸
                            direction = new Vector2d(this.center.Value.X - this.point.Value.X, this.center.Value.Y - this.point.Value.Y);
                        } else if (lcline.Length < this.raduis) {
                            //向外部延伸
                            direction = new Vector2d(this.point.Value.X - this.center.Value.X, this.point.Value.Y - this.center.Value.Y);
                        }
                        if (direction.Length != 0) {
                            //新的移动后的点位
                            Vector2d lidisptpos = this.point.Value + (new Vector2d(direction.X * dis, direction.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                            this.point = lidisptpos;
                        }
                        #endregion
                        CreateDimElement();
                        goto End;

                    }
                }
                else
                {
                    goto Step0;
                }
            }
  
            End:
            this.EndCreating();

        }
        private void CreateDimElement()
        {
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("DIMRADIAL");
            var DimRadial = doc.CreateObject<DimRadial>();
            DimRadial.Start = this.point.Value;
            DimRadial.End = this.center.Value;
            DimRadial.Dimtext =(this.raduis).ToString("0.00");
            doc.ModelSpace.InsertElement(DimRadial);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }
       

        /// <summary>
        /// 选中的对象
        /// </summary>
        /// <param name="elements"></param>
        /// <returns></returns>
        private bool CreateSelects(LcElement elements)
        {

         
                if (elements is LcCircle|| elements is LcArc) {
                    return true;

                }
               
            return false;

        }


        /// <summary>
        /// 对一个坐标点按照一个中心进行旋转
        /// </summary>
        /// <param name="center">中心点</param>
        /// <param name="p1">要旋转的点</param>
        /// <param name="angle">旋转角度，笛卡尔直角坐标</param>
        /// <returns></returns>
        private Vector2d PointRotate(Vector2d center, Vector2d p1, double angle)
        {
            Vector2d tmp = new Vector2d();
            double angleHude = angle * Math.PI / 180;/*角度变成弧度*/
            double x1 = (p1.X - center.X) * Math.Cos(angleHude) + (p1.Y - center.Y) * Math.Sin(angleHude) + center.X;
            double y1 = -(p1.X - center.X) * Math.Sin(angleHude) + (p1.Y - center.Y) * Math.Cos(angleHude) + center.Y;
            tmp.X = (int)x1;
            tmp.Y = (int)y1;
            return tmp;
        }
        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }
       
        

        public override void CreateElement(LcElement element, Matrix3d matrix)
        {
            DocumentManager.CurrentRecorder.BeginAction("Circle");
            var dim = element as DimRadial;
            this.vportRt.ActiveElementSet.AddDimRadial(matrix.MultiplyPoint(dim.Start), matrix.MultiplyPoint(dim.End),dim.Dimtext);
            DocumentManager.CurrentRecorder.EndAction();
        }
        public override void CreateElement(LcElement element,Vector2d basePoint, double scaleFactor)
        {
            var circle = element as LcCircle;
            Matrix3d matrix3 = Matrix3d.Scale(scaleFactor, basePoint);
            this.vportRt.ActiveElementSet.AddCircle(matrix3.MultiplyPoint(circle.Center), circle.Radius * scaleFactor);
        }
        public override void CreateElement(LcElement element, Vector2d basePoint, Vector2d scaleVector)
        {
            var circle = element as LcCircle;
            Matrix3d matrix3 = Matrix3d.Scale(scaleVector, basePoint);
            this.vportRt.ActiveElementSet.AddCircle(matrix3.MultiplyPoint(circle.Center), circle.Radius * Vector2d.Distance(basePoint, scaleVector));
        }
        public override void Draw(SKCanvas canvas, LcElement element, Matrix3d matrix)
        {
            var dim = element as DimRadial;
            var mstart = matrix.MultiplyPoint(dim.Start);
            var mend = matrix.MultiplyPoint(dim.End);
            var mtext = dim.Dimtext;
            var start = this.vportRt.ConvertWcsToScr(mstart).ToSKPoint();
            var end = this.vportRt.ConvertWcsToScr(mend).ToSKPoint();
            //get Layer color 
            //bool isDragCopy = (matrix != Matrix3d.Zero);
            //var pen = this.GetDrawPen(dim, isDragCopy);
            var pen = this.GetDrawPen(element);
            if (pen == Constants.defaultPen)
            {
                //TODO:这里可以考虑将实线用颜色做KEY，对SKPaint进行缓存
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {

                    canvas.DrawLine(start, end, elePen);
                    canvas.DrawText(mtext, start, elePen);
                }
            }
            else
            {
                canvas.DrawLine(start, end, pen);
                canvas.DrawText(mtext, start, pen);
            }
            #region
            var path = DrawArrow(dim.Start, dim.End);
            using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
            {
                //elePen.Color = SKColors.Red;
                elePen.Style = SKPaintStyle.StrokeAndFill;
                elePen.IsAntialias = true;
                elePen.StrokeWidth = 2;
                //绘制路径
                canvas.DrawPath(path, elePen);
            }
            #endregion
        }

        /// <summary>
        /// 画箭头
        /// </summary>
        /// <param name="start">箭头指向点</param>
        /// <param name="end"></param>
        /// <param name="extraAngle">额外旋转角度</param>
        /// <returns></returns>
        private SKPath DrawArrow(Vector2d start, Vector2d end, double extraAngle = 0)
        {
            LcLine lcline = new LcLine();
            lcline.Start = start;
            lcline.End = end;
            var radian = lcline.Angle;

            var startve = new Vector2d(lcline.Start.X, lcline.Start.Y);
            var arrowtwove = new Vector2d(lcline.Start.X + 100, lcline.Start.Y + 30);
            var arrowendve = new Vector2d(lcline.Start.X + 100, lcline.Start.Y - 30);
            var angle = Utils.RadianToDegree(radian) + extraAngle;
            arrowtwove = Vector2d.Rotate(arrowtwove, startve, angle);
            arrowendve = Vector2d.Rotate(arrowendve, startve, angle);

            var pointone = this.vportRt.ConvertWcsToScr(startve).ToSKPoint();
            var pointtwo = this.vportRt.ConvertWcsToScr(arrowtwove).ToSKPoint();
            var pointthree = this.vportRt.ConvertWcsToScr(arrowendve).ToSKPoint();

            var path = new SKPath();
            path.FillType = SKPathFillType.EvenOdd;
            //外圈 顺时针
            path.MoveTo((float)pointone.X, (float)pointone.Y);    //起点
            path.LineTo((float)pointtwo.X, (float)pointtwo.Y);
            path.LineTo((float)pointthree.X, (float)pointthree.Y);
            path.Close();
            return path;
        }

        public override void DrawAuxLines(SKCanvas canvas)
        {
            //if (this.point != null)
            //{
            //    var mp = this.vportRt.PointerMovedPosition.ToVector2d();
            //    var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
            //    DrawAuxLine(canvas, this.point.Value, wcs_mp);
            //}
        }

        private void DrawAuxLine(SKCanvas canvas, Vector2d p0, Vector2d p1)
        {
            //var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            //var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            ////辅助元素的颜色 
            //canvas.DrawLine(sk_pre, sk_p, Constants.auxElementPen);
            ////辅助曲线的颜色，包括辅助长度，辅助角度等
        }

        #region Grip
        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var dimradial = element as DimRadial;
            var grips = new List<ControlGrip>();
            var gripStart = new ControlGrip {
                Element = dimradial,
                Name = "Start",
                Position = dimradial.Start
            };
            
            var gripEnd = new ControlGrip
            {
                Element = dimradial,
                Name = "End",
                Position = dimradial.End
            };
            grips.Add(gripStart);
            
            grips.Add(gripEnd);
            return grips.ToArray();
        }
        private string _gripName;
        private Vector2d _position;
        private DimRadial _dimradial;

        public override void SetDragGrip(LcElement element, string gripName, Vector2d position, bool isEnd)
        {
            var dimradial = element as DimRadial;

            _dimradial = dimradial;
            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                //半径
                var radialradius = _dimradial.Length;
                //需要移动的向量方向
                Vector2d direction = new Vector2d(0, 0);
                var radialstart = _dimradial.Start;
                var radialend = _dimradial.End;

                if (gripName == "Start")
                {
                    LcLine lcline = new LcLine(radialend, _position);
                    //需要移动的距离
                    double dis = Math.Abs(lcline.Length - radialradius);
                    if (lcline.Length > radialradius)
                    {
                        //向内延伸
                        direction = new Vector2d(radialend.X - _position.X, radialend.Y - _position.Y);
                    }
                    else if (lcline.Length < radialradius)
                    {
                        //向外部延伸
                        direction = new Vector2d(_position.X - radialend.X, _position.Y - radialend.Y);
                    }
                    Vector2d newpoint = new Vector2d(_position.X, _position.Y);
                    if (direction.Length != 0)
                    {
                        //新的移动后的点位
                        Vector2d lidisptpos = _position + (new Vector2d(direction.X * dis, direction.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                        newpoint = lidisptpos;
                    }
                    radialstart = newpoint;
                    _dimradial.Set(start: radialstart);
                }
                else if (gripName == "End")
                {
                    direction = new Vector2d(radialstart.X - _position.X, radialstart.Y - _position.Y);
                    radialend = new Vector2d(_position.X, _position.Y);
                    Vector2d lidisptpos = _position + (new Vector2d(direction.X * radialradius, direction.Y * radialradius)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                    radialstart = lidisptpos;
                    _dimradial.Set(end: position);
                    _dimradial.Set(start: radialstart);
                }
            }
        }


        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_dimradial == null) return;
            //半径
            var radialradius = _dimradial.Length;
            //需要移动的向量方向
            Vector2d direction = new Vector2d(0, 0);
            var radialstart = _dimradial.Start;
            var radialend = _dimradial.End;
            if (_gripName == "Start")
            {
                LcLine lcline = new LcLine(radialend, _position);
                //需要移动的距离
                double dis = Math.Abs(lcline.Length - radialradius);
                if (lcline.Length > radialradius)
                {
                    //向内延伸
                    direction = new Vector2d(radialend.X - _position.X, radialend.Y - _position.Y);
                }
                else if (lcline.Length < radialradius)
                {
                    //向外部延伸
                    direction = new Vector2d(_position.X - radialend.X, _position.Y - radialend.Y);
                }
                Vector2d newpoint = new Vector2d(_position.X, _position.Y);
                if (direction.Length != 0)
                {
                    //新的移动后的点位
                    Vector2d lidisptpos = _position + (new Vector2d(direction.X * dis, direction.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                    newpoint = lidisptpos;
                }
                radialstart = newpoint;
            }
            if (_gripName == "End")
            {
                if (_position == radialend) return;
                direction = new Vector2d(radialstart.X - _position.X, radialstart.Y - _position.Y);
                radialend = new Vector2d(_position.X, _position.Y);
                Vector2d lidisptpos = _position + (new Vector2d(direction.X * radialradius, direction.Y * radialradius)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                radialstart = lidisptpos;
            }
            var start = this.vportRt.ConvertWcsToScr(radialstart);
            var end = this.vportRt.ConvertWcsToScr(radialend);
            var pen = this.GetDrawPen(_dimradial);
            if (pen == Constants.defaultPen)
            {
                using (var elePen = new SKPaint { Color = new SKColor(_dimradial.GetColorValue()), IsStroke = true })
                {
                    canvas.DrawLine(start.ToSKPoint(), end.ToSKPoint(), elePen);
                    canvas.DrawText(_dimradial.Dimtext, start.ToSKPoint(), elePen);
                }
            }
            else {
                canvas.DrawLine(start.ToSKPoint(), end.ToSKPoint(), pen);
                canvas.DrawText(_dimradial.Dimtext, start.ToSKPoint(), pen);
            }
            var path = DrawArrow(radialstart, _dimradial.End);
            using (var elePen = new SKPaint { Color = new SKColor(_dimradial.GetColorValue()), IsStroke = true })
            {
                //elePen.Color = SKColors.Red;
                elePen.Style = SKPaintStyle.StrokeAndFill;
                elePen.IsAntialias = true;
                elePen.StrokeWidth = 2;
                //绘制路径
                canvas.DrawPath(path, Constants.draggingPen);
            }
        }

        #endregion

        public override List<PropertyObserver> GetPropertyObservers()
        {
            return new List<PropertyObserver>()
            {
                
            };
        }
    }
}
